<?php 
namespace OAuth2\Example\Server\Token;
/**
 * Token handler implementatin
 * @author Wojciech Kupiec <kupiec.w@gmail.com>
 */
class Handler {
    
    protected $_oauth;
    protected $_options;
    
    function __construct(\OAuth2\Server $oauth, $options = array('display_errors' => true))
    {
        $this->setOauth($oauth);
        $this->setOptions($options);
    }
    

  /**
   * Internal function used to get the client credentials from HTTP basic
   * auth or POST data.
   *
   * @return
   *   A list containing the client identifier and password, for example
   * @code
   * return array(
   *   $_POST["client_id"],
   *   $_POST["client_secret"],
   * );
   * @endcode
   *
   * @see http://tools.ietf.org/html/draft-ietf-oauth-v2-10#section-2
   *
   * @ingroup oauth2_section_2
   */
  protected function getClientCredentials() { 
    if (isset($_SERVER["PHP_AUTH_USER"]) && $_POST && isset($_POST["client_id"]))
      throw new \OAuth2\Server\Exception(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_CLIENT);

    // Try basic auth
    if (isset($_SERVER["PHP_AUTH_USER"]))
      return array($_SERVER["PHP_AUTH_USER"], $_SERVER["PHP_AUTH_PW"]);

    // Try POST
    if ($_POST && isset($_POST["client_id"])) {
      if (isset($_POST["client_secret"]))
        return array($_POST["client_id"], $_POST["client_secret"]);

      return array($_POST["client_id"], NULL);
    }

    // No credentials were specified
    throw new \OAuth2\Server\Exception(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_CLIENT);
  }
    
    /**
     * Handles token request
     */
    public function handleTokneRequest() {
        try {
            $input = $this->getGrantAccessTokenParams();
            $token = $this->getOauth()->grantAccessToken($this->getClientCredentials(),$input["grant_type"], $input["code"], $input["redirect_uri"], $input["username"], $input["password"], $input["assertion_type"], $input["assertion"], $input["refresh_token"], $input["scope"]);
            $this->sendJsonHeaders();
            echo json_encode($token);
        } catch(\OAuth2\Server\Exception $excption) {
            $this->errorJsonResponse($excption->getHttpStatusCode(), $excption->getError(), $excption->getMessage(), $excption->getErrorUri());
        }
    }
    
    /**
     * Oauth getter
     * @return type 
     */
     public function getOauth()      {
         return $this->_oauth;
     }

     /**
      * Oauth setter
      * 
      * @param type $oauth 
      */
     public function setOauth(\OAuth2\Server $oauth)
     {
         $this->_oauth = $oauth;
     }
     
     /**
      * Options getter
      *
      * @return array
      */
     public function getOptions() 
     {
         return $this->_options;
     }

     /**
      * Options setter
      *
      * @param array $options 
      */
     public function setOptions($options)
     {
         $this->_options = $options;
     }

    
    /**
    * Send out error message in JSON.
    *
    * @param $http_status_code
    *   HTTP status code message as predefined.
    * @param $error
    *   A single error code.
    * @param $error_description
    *   (optional) A human-readable text providing additional information,
    *   used to assist in the understanding and resolution of the error
    *   occurred.
    * @param $error_uri
    *   (optional) A URI identifying a human-readable web page with
    *   information about the error, used to provide the end-user with
    *   additional information about the error.
    *
    * @see http://tools.ietf.org/html/draft-ietf-oauth-v2-10#section-4.3
    *
    * @ingroup oauth2_error
    */
    public function errorJsonResponse($http_status_code, $error, $error_description = NULL, $error_uri = NULL) {
        $result['error'] = $error;
        $options = $this->getOptions();
        $displayErrors = isset($options['display_errors']) && $options['display_errors'] === true;
        
        if ($displayErrors && $error_description)
          $result["error_description"] = $error_description;
        
        if ($displayErrors && $error_uri)
          $result["error_uri"] = $error_uri;

        header("HTTP/1.1 " . $http_status_code);
        $this->sendJsonHeaders();
        echo json_encode($result);


        exit;
    }


    /**
    * Send out HTTP headers for JSON.
    *
    * @see http://tools.ietf.org/html/draft-ietf-oauth-v2-10#section-4.2
    * @see http://tools.ietf.org/html/draft-ietf-oauth-v2-10#section-4.3
    *
    * @ingroup oauth2_section_4
    */
    public function sendJsonHeaders() {
        header("Content-Type: application/json");
        header("Cache-Control: no-store");
    }

    /**
    * Filters input arguments for grantAccessToken() method
    * It is recommended to override this method in your application
    *
    * @return array
    */
    public function getGrantAccessTokenParams() {
        $filters = array(
          "grant_type" => array("filter" => FILTER_VALIDATE_REGEXP, "options" => array("regexp" => OAUTH2_GRANT_TYPE_REGEXP), "flags" => FILTER_REQUIRE_SCALAR),
          "scope" => array("flags" => FILTER_REQUIRE_SCALAR),
          "code" => array("flags" => FILTER_REQUIRE_SCALAR),
          "redirect_uri" => array("filter" => FILTER_SANITIZE_URL),
          "username" => array("flags" => FILTER_REQUIRE_SCALAR),
          "password" => array("flags" => FILTER_REQUIRE_SCALAR),
          "assertion_type" => array("flags" => FILTER_REQUIRE_SCALAR),
          "assertion" => array("flags" => FILTER_REQUIRE_SCALAR),
          "refresh_token" => array("flags" => FILTER_REQUIRE_SCALAR),
        );

        $input = filter_input_array(INPUT_POST, $filters);
        return $input;
    }
}
